﻿using System;
using Cashbook.Models;
using SQLite;
using Xamarin.Forms;

namespace Cashbook.Services
{
	/// <summary>
	/// Class to handle DB connection
	/// </summary>
	public static class Database
	{
		//this have to reflect the last database version when 
		//the application is shipped
		//must be updated with every database change
		public const int LAST_DATABASE_VERSION = 1;

		public static SQLiteAsyncConnection database;

		/// <summary>
		/// get the connection from the database using Xamarin Forms dependency service.
		/// the real implementation (folder path) is in platform specific classes 
		/// </summary>
		/// <returns></returns>
		/// 
		public static SQLiteAsyncConnection GetDBConnection()
		{
			//use dependency service for getting the platform connection
			database = new SQLiteAsyncConnection(DependencyService.Get<IFileHelper>().GetLocalFilePath("CashbooksDB.db3"));
			database.CreateTableAsync<Bill>().Wait();
			database.CreateTableAsync<Customer>().Wait();
			database.CreateTableAsync<Statement>().Wait();
            database.ExecuteAsync("PRAGMA foreign_keys = ON");

            UpgradeDatabaseIfNecessary();

			

			return database;
		}

		private static void SetDatabaseToVersion(int version)
		{
			database.ExecuteAsync("PRAGMA user_version = " + version);
		}

		private static System.Threading.Tasks.Task<int> GetDatabaseVersion()
		{
			return database.ExecuteScalarAsync<int>("PRAGMA user_version");
		}

		private static void UpgradeDatabaseIfNecessary()
		{
			//the first time ever we get this value after the database creation
			//this should be equals 0. but it's ok and will perform the correct
			//updates in the switch.
            int currentDbVersion = GetDatabaseVersion().Result;

			if (currentDbVersion < LAST_DATABASE_VERSION)
			{
				//we have to ignore the current database updates, so start from the next
				int startUpgradingFrom = currentDbVersion + 1;
				//if we are are, database upgrade is needed
				switch (startUpgradingFrom)
				{
					case 1: //starting version
					case 2:
						UpgradeFrom1To2();
						goto case 3;
					case 3:
						UpgradeFrom2To3();
						goto case 4;
					case 4: //ecc.. ecc..
						break;
					default:
						//if we are here something with the update went wrong,
						//deleting and recreating the database is the only
						//possible action to perform
						throw new Exception("something went really wrong");
				}

				SetDatabaseToVersion(LAST_DATABASE_VERSION);
			}
		}

		private static void UpgradeFrom1To2() { }

		private static void UpgradeFrom2To3() { }
	}
}